//
//  TextSegment.m
//  NewsMaker Touch
//
//  Created by Reisen on 10/8/14.
//  Copyright (c) 2014 Reisen. All rights reserved.
//

#import "TextSegment.h"
#import "Utility.h"
#import "VideoRecorder.h"
#import "TalkDefine.h"

@implementation TextSegment

-(BOOL)canPreview
{
    NSString* path = [self.root stringByAppendingPathComponent:self.src];
    if(![[NSFileManager defaultManager] fileExistsAtPath:path])
        return NO;
    
    return YES;
}

-(void) initializePreview
{
    PreviewView* prev = self.currentPreviewLayer;
    prev.layoutView.hidden = NO;
    
    [prev.layoutView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    
    [self initializePreviewInView:prev.layoutView];
}

-(void) initializePreviewInView:(UIView*)view
{
    NSString* path = [self.root stringByAppendingPathComponent:self.src];
    
    NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:nil];

    TLDebugS(@"Load layout from %@", path);

    if(dict == nil) return;
    
    CGFloat wFactor = view.bounds.size.width / 768;
    CGFloat hFactor = view.bounds.size.height / 1024;
    
    [self loadBackgroundInView:view fromDict:dict];
        
    //============================
    
    animationMode = [dict[@"animationMode"] intValue];
    
    duration = [dict[@"animationDuration"] intValue];
    
    //============================
    
    textView = [UILabel new];
    textView.textAlignment = NSTextAlignmentCenter;
    textView.numberOfLines = 0;
    [view addSubview:textView];
    
    NSDictionary* subtitleDict = dict[@"text"];
    textView.backgroundColor = [Utility UIColorFromNSString:subtitleDict[@"background"]];
    textView.textColor = [Utility UIColorFromNSString:subtitleDict[@"foreground"]];
    
    fontSize = [subtitleDict[@"fontSize"] floatValue] * hFactor;
    textView.font = [UIFont systemFontOfSize:fontSize];
    
    
    CGRect frame = CGRectFromString(subtitleDict[@"frame"]);
    
    textView.frame = CGRectMake(frame.origin.x * wFactor, frame.origin.y * hFactor, frame.size.width * wFactor, frame.size.height * hFactor);
    
    //textView.text = subtitleDict[@"text"];
    [self getTextFromJSON:[self.root stringByAppendingPathComponent:subtitleDict[@"content"]]];
    
//    [textView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
    //============================
    
    if(bgmPlayer != nil)
    {
        [bgmPlayer stop];
        bgmPlayer = nil;
    }
    
    NSString* BGM = dict[@"BGM"];
    
    if(BGM != nil)
    {
        NSString* folderPath = self.fileRoot;
        //[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Music"];
        
        NSString* fileName = [BGM stringByAppendingPathExtension:@"mp3"];
        
        bgmPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]] error:nil];
        bgmPlayer.numberOfLoops = -1; //Infinite
    }
    
    [self paginateText];
}

-(void)getTextFromJSON:(NSString*)path
{
    NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:nil];

    TLDebugS(@"Load text from %@", dict);

    NSArray* arr = dict[@"credits_list"];
    
    BOOL isZh = [[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:@"zh"].location != NSNotFound;
//    isZh =YES;
    NSString* s = @"";
    for (NSDictionary* lineDict in arr)
    {
        if(s.length > 0) s = [s stringByAppendingString:@"~~~"];
        
        if(isZh) s = [s stringByAppendingString:lineDict[@"cn"]];
        else s = [s stringByAppendingString:lineDict[@"en"]];
    }

    TLDebugS(@"s = %@", s);

    textView.text = s;
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    UITextView *txtview = object;
    CGFloat topoffset = ([txtview bounds].size.height - [txtview contentSize].height * [txtview zoomScale])/2.0;
    topoffset = ( topoffset < 0.0 ? 0.0 : topoffset );
//    txtview.contentOffset = (CGPoint){.x = 0, .y = -topoffset};
}

-(void)play
{
    if(isPaused)
    {
        TLDebugS(@"Unpause!");
 
        isPaused = NO;
        [bgmPlayer play];
        return;
    }
    
    isPaused = NO;
    
    [self paginateText];
    
    [bgmPlayer play];
    
    
    [self startPlaybackLoop];
}

-(void) startPlaybackLoop
{
    if(playbackTimer!=nil)
    {
        [playbackTimer invalidate];
        playbackTimer = nil;
    }
    {
        lastPlaybackLoop = playbackStarted = [NSDate timeIntervalSinceReferenceDate];
        
        isPlaying = YES;
        
        [self playbackLoop:nil];
        
        playbackTimer = [NSTimer scheduledTimerWithTimeInterval:0.025 target:self selector:@selector(playbackLoop:) userInfo:nil repeats:YES];
    }
}

-(void)playbackLoop:(NSTimer*)timer
{
    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
    
    @autoreleasepool {
        if(isPaused)
        {
            playbackStarted += now - lastPlaybackLoop;
            lastPlaybackLoop = now;
            return;
        }
        lastPlaybackLoop = now;
        
        double gap = now - playbackStarted;
        
        [self seekToTime:gap];
        
        if(gap >= duration)
            [self stop];
    }
}

-(CGFloat)seekToTime:(float)gap
{
    double maxTime = duration - 2;
    double interpolation = gap / maxTime;
    
    if(interpolation > 1) interpolation = 1;
    
    if(gap > duration) gap = duration;
    
    if(bgmPlayer != nil && gap > maxTime - 3)
    {
        double inty = (gap - (maxTime - 3)) / 3;
        if(inty < 0) inty = 0;
        if(inty > 1) inty = 1;
        
        bgmPlayer.volume = 1 - inty;
    }
    
    float retval = 0;
    
    if(animationMode == 0)
    {
        NSInteger pageCount = paginatedText.count;
        
        float pageDuration = maxTime / pageCount;
        
        float fadeDuration = 0.5f;
        
        if(pageDuration < fadeDuration * 2)
            fadeDuration = pageDuration / 2;
        
        NSInteger curPage = (NSInteger)(interpolation * pageCount);
        
        if(curPage >= pageCount) curPage = pageCount - 1;
        
        float alpha = 1;
        
        if(gap < maxTime)
        {
            float localGap = gap - (int)(gap / pageDuration) * pageDuration;
            
            if(localGap < fadeDuration && curPage != 0)
            {
                alpha = localGap / fadeDuration;
            }
            
            else if(localGap > pageDuration - fadeDuration && curPage != pageCount - 1)
            {
                alpha = (pageDuration - localGap) / fadeDuration;
            }
        }
        
        CGFloat r = 0, g = 0, b = 0;
        [textView.textColor getRed:&r green:&g blue:&b alpha:nil];
        textView.textColor = [UIColor colorWithRed:r green:g blue:b alpha:alpha];
        
        textView.text = paginatedText[curPage];
        
        retval = alpha;
    }
    
    else if(animationMode == 2)
    {
        NSInteger pageCount = paginatedText.count;
        
        float pageDuration = maxTime / pageCount;
        
        float fadeDuration = 0.5f;
        
        if(pageDuration < fadeDuration * 2)
            fadeDuration = pageDuration / 2;
        
        NSInteger curPage = (int)(interpolation * pageCount);
        
        if(curPage >= pageCount) curPage = pageCount - 1;
        
        float alpha = 1;
        
        CGFloat width = [textView superview].bounds.size.width;
        
        if(gap < maxTime)
        {
            float localGap = gap - (int)(gap / pageDuration) * pageDuration;
            
            if(localGap < fadeDuration)
            {
                alpha = localGap / fadeDuration;
                
                textView.transform = CGAffineTransformMakeTranslation(width + (-width) * alpha, 0);
            }
            
            else if(localGap > pageDuration - fadeDuration)
            {
                alpha = (pageDuration - localGap) / fadeDuration;
                alpha = 1 - alpha;
                
                textView.transform = CGAffineTransformMakeTranslation((-width) * alpha, 0);
                
            }
            
            else textView.transform = CGAffineTransformIdentity;
            
            retval = alpha;
        }
        
        NSString* text = paginatedText[curPage];
        
        if([textView.attributedText.string isEqualToString:text])
            return retval;
        
        NSMutableAttributedString* attrText = [[NSMutableAttributedString alloc] initWithString:text];

        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setAlignment:NSTextAlignmentCenter];
        [attrText addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attrText.length)];
        
        [attrText addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, attrText.length)];
        
        NSShadow *shadowDic=[[NSShadow alloc] init];
        [shadowDic setShadowBlurRadius:2.0];
        [shadowDic setShadowColor:[UIColor grayColor]];
        [shadowDic setShadowOffset:CGSizeMake(0, 3)];
        [attrText addAttribute:NSShadowAttributeName value:shadowDic range:NSMakeRange(0, attrText.length)];
        
        UIFont* font1 = [UIFont systemFontOfSize:fontSize];
        
        if([text rangeOfString:@"\n"].location != NSNotFound && [text rangeOfString:@"©"].location == NSNotFound)
        {
            UIFont* font2 = [UIFont fontWithName:textView.font.fontName size:font1.pointSize * 0.8f];
            
            NSInteger breakLoc = [text rangeOfString:@"\n"].location;
            
            [attrText addAttribute:NSFontAttributeName value:font2 range:NSMakeRange(0, breakLoc)];
            [attrText addAttribute:NSFontAttributeName value:font1 range:NSMakeRange(breakLoc + 1, text.length - (breakLoc + 1))];
        }
        
        else [attrText addAttribute:NSFontAttributeName value:font1 range:NSMakeRange(0, text.length)];
        
        textView.attributedText = attrText;
    }
    else
    {
        /*
        float min = -textView.frame.size.height;
        
        //Content > frame => Text end at bottom
        float max = textView.contentSize.height;//-self.subtitleView.frame.size.height;
        
        //Content < frame => text end at center
        if(max < 0) max /= 2;
        
        float y = min + interpolation * (max - min);
        
        [textView setContentOffset:CGPointMake(0, y) animated:NO];
         */
    }
    
    return retval;
}


-(void)stop
{
    [playbackTimer invalidate];
    playbackTimer=nil;
    
    isPlaying = NO;
    isPaused = NO;
    
    [bgmPlayer stop];
    textView.hidden = YES;
    
    [self.currentPreviewLayer playNextSegment];
}



-(void)pause
{
    isPaused = YES;
    [bgmPlayer pause];
}

-(void)paginateText
{
    paginatedText = [textView.text componentsSeparatedByString:@"~~~"];
}

//Running on main thread;
//*
-(void) encodeVideo
{
    int w = 768 * 3 / 4;
    int h = 1024 * 3 / 4;
    
    layoutView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, w, h)];
    
    [self initializePreviewInView:layoutView];
    
    TLDebugS(@"Duration = %f", duration);
    
    NSString* outputPath = [[Utility rootStorage] stringByAppendingPathComponent:@"text.mp4"];
    //VideoRecorder*
    recorder = [[VideoRecorder alloc] initWithWidth:w Height:h];
    recorder.recordPath = outputPath;
    recorder.delegate = self;
    [recorder startRecording];
    
    lastKeyframe = -1;
    [self encodeLoop:[NSNumber numberWithFloat:0]];
}


-(void)encodeLoop:(NSNumber*)stamp
{
    CGFloat t = [stamp floatValue];
    
    if(t >= duration)
    {
        //*
        [self seekToTime:duration];
        UIGraphicsBeginImageContextWithOptions(layoutView.frame.size, YES, 1);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSetInterpolationQuality(ctx, kCGInterpolationNone);
        
        [layoutView.layer renderInContext:ctx];
        UIImage* screenshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        recorder.currentScreen = screenshot;
        [recorder encodeFrameAtTime:CMTimeMakeWithSeconds(duration, 1000)];
        //*/
  //      TLDebugS(@"Encode %f", duration);
        
        [recorder stopRecording];
        
        recorder = nil;
        layoutView = nil;
        
        self.progress = 1;
        TLDebugS(@"Done!!!");
        return;
    }
    
   // [Utility startTiming];
    CGFloat keyframe = [self seekToTime:t];
    
//    if(YES)
    if(keyframe != lastKeyframe)
    {
        UIGraphicsBeginImageContextWithOptions(layoutView.frame.size, YES, 1);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSetInterpolationQuality(ctx, kCGInterpolationNone);
        
        [layoutView.layer renderInContext:ctx];
        //    [layoutView drawViewHierarchyInRect:layoutView.bounds afterScreenUpdates:YES];
        UIImage* screenshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        recorder.currentScreen = screenshot;
        [recorder encodeFrameAtTime:CMTimeMakeWithSeconds(t, 1000)];
        
    //    TLDebugS(@"Encode main %f", t);
        
        lastKeyframe = keyframe;
    }
    
    else
    {
 //       TLDebugS(@"Skip!");
        lastKeyframe = -1;
    }
    
    self.progress = t / duration;
    
    //   [Utility endTimingWithTag:@"Text Frame"];
    
    [self performSelector:@selector(encodeLoop:) withObject:[NSNumber numberWithFloat:t + 1.0f / 25] afterDelay:0.001f];
}

-(NSString*)videoInformation
{
    return [[Utility rootStorage] stringByAppendingPathComponent:@"text.mp4"];
}

-(NSMutableArray*)audioInformationWithStart:(float)start
{
    float audioDuration = [bgmPlayer duration];
    
    NSMutableArray* arr = [NSMutableArray array];
    
    if(bgmPlayer == nil) return arr;
    
    NSString* path = [self.root stringByAppendingPathComponent:self.src];
    NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:nil];
    
    if(dict == nil) return arr;
    
    NSString* BGM = dict[@"BGM"];
//    NSString* folderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Music"];
    
    NSString* folderPath = self.fileRoot;
    NSString* fileName = [BGM stringByAppendingPathExtension:@"mp3"];
    
    for(float i = 0; i < duration; i += audioDuration)
    {
        float loopDur = audioDuration;
        
        if(i + audioDuration > duration) loopDur = duration - i;
        
        [arr addObject:@{@"path": [folderPath stringByAppendingPathComponent:fileName], @"start":[NSNumber numberWithFloat:i + start], @"duration":[NSNumber numberWithFloat:loopDur], @"track":[NSNumber numberWithInt:0]}];
    }
    return arr;
}

-(float)getDuration
{
    
    if(duration == 0)
    {
        NSString* path = [self.root stringByAppendingPathComponent:self.src];
        
        NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:NSJSONReadingMutableContainers error:nil];
        duration = [dict[@"animationDuration"] intValue];
    }
    return duration;
}
@end
